﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Configuration;
using System.Data;
using STS.Common;
using STS.Schema.Interfaces;
using STS.Schema.Factory;
using STS.Interfaces;
using STS.Common.Enums;

namespace STS.Schema
{
    public class DbUtils
    {
        private static Dictionary<string, DbProviderFactory> _providerFactory = new Dictionary<string, DbProviderFactory>();

        private static DbProviderFactory GetProviderFactory(ConnectionInfo connectionInfo)
        {
            if (!string.IsNullOrWhiteSpace(connectionInfo.ProviderName))
            {
                if (_providerFactory.ContainsKey(connectionInfo.ProviderName))
                {
                    return _providerFactory[connectionInfo.ProviderName];
                }

                var providerExists = DbProviderFactories
                                            .GetFactoryClasses()
                                            .Rows.Cast<DataRow>()
                                            .Any(r => r[2].Equals(connectionInfo.ProviderName));
                if (providerExists)
                {
                    var factory = DbProviderFactories.GetFactory(connectionInfo.ProviderName);
                    _providerFactory.Add(connectionInfo.ProviderName, factory);

                    return factory;
                }
            }

            return null;
        }

        public static DbConnection GetConnection(ConnectionInfo connectionInfo)
        {
            DbProviderFactory factory = GetProviderFactory(connectionInfo);

            if (factory == null)
            {
                throw new STSException("Unknown connection type.");
            }

            DbConnection conn = factory.CreateConnection();
            conn.ConnectionString = connectionInfo.ConnectionString;

            return conn;
        }

        public static DbServer GetServer(ConnectionInfo connectionInfo)
        {
            using (DbConnection connection = GetConnection(connectionInfo))
            {
                connection.Open();

                DbServer srv = new DbServer(connection.DataSource, connectionInfo)
                {
                    ServerVersion = connection.ServerVersion,
                    _databseName = connection.Database
                };

                switch (connectionInfo.ProviderType)
                {
                    case ProviderType.MSSql:
                        switch (srv.ServerVersion)
                        {
                            case "10.50.2500":
                                srv.Factory = new SqlServer2008R2SchemaFactory(srv);
                                break;
                            case "10.00.5500":
                                srv.Factory = new SqlServer2008SchemaFactory(srv);
                                break;
                            default:
                                break;
                        }
                        break;
                    case ProviderType.MySql:
                        break;
                    case ProviderType.Oracle:
                        break;
                }

                return srv;
            }
        }

        public static DbDataReader ExecuteReader(ConnectionInfo connectionInfo, string query)
        {
            DbConnection connection = GetConnection(connectionInfo);
            connection.Open();

            DbCommand cmd = connection.CreateCommand();
            cmd.CommandText = query;

            return cmd.ExecuteReader();
        }
    }
}
